/*
 * @Author: yangzonglong
 * @Date: 2021-05-08 14:07:56
 * @version: v1.0.0
 * @Descripttion: 表单预览
 * @LastEditors: yangzonglong
 * @LastEditTime: 2023-09-12 15:53:00
 * @Auditor:
 */
import React, { useState, useEffect, useMemo, useCallback, useRef, forwardRef, useImperativeHandle } from 'react';
import { View } from './../../components/fd';
import { getForm, getLformView } from './api';

const pd: React.CSSProperties = {
  padding: '20px',
  display: 'flex',
  flexDirection: 'column',
  height: '100%'
};

const LFOFM_URL = '/fd/data_view_extra';
interface FormViewProps {
  url?: string; // 具体的url
  formName?: string; // LFORM所需
  state?: string; // 流程节点线路信息，判断当前所在节点哪些字段可编辑
  formId?: string;
  taskId?: string;
  formDataId?: string;
  isLformHtml?: boolean; // 以html模式加载LFORM
  action?: string; // 指定 postMessage action
  onOk?(data?: string): any;
  onTrigger?(data: string): void;
  disabled?: boolean; // 只对GFORM有效，LFORM 可通过isLformHtml来替代
  business?: any;
}
export interface FormViewRefProps {
  getData(options?: any, required?: boolean, next?: Function, executeSubmitScript?: boolean): void;
  getGFORM_Data(): void;
}

export default forwardRef(
  ({ url, formId, formDataId, isLformHtml, action, onOk, onTrigger, formName, state, taskId, disabled, business }: FormViewProps, ref: React.Ref<FormViewRefProps>) => {
    const lformRef = useRef<HTMLIFrameElement>(null);
    const gformRef = useRef<any>(null);
    const formEngine = useRef('');
    const [formData, setFormData] = useState('');
    const [formInfo, setFormInfo] = useState<any>({});
    const [content, setContent] = useState(''); // 表单结构
    const [enviromentConfig, setEnviromentConfig] = useState(undefined);

    useImperativeHandle(ref, () => ({
      async getData(options, required = true, next?: Function, executeSubmitScript = true) {
        if (formEngine.current === 'LFORM') {
          lformRef.current?.contentWindow?.postMessage(
            {
              action: 'saveFormData',
              firstCommit: true,
            },
            '*'
          );
        } else {
          if(gformRef.current) {
            const data = await gformRef.current?.validateFields(required, options, executeSubmitScript);

            if(data._transform) {
              Object.keys(data._transform).forEach(field => {
                const obj = data[field];

                for(let k in obj) {
                  data[`${field}.${k}`] = obj[k] 
                }
              })
            }
            
            if (data) {
              const stringifyData = JSON.stringify(data);
              setFormData(stringifyData);
              if (disabled && editFields.length === 0) {
                if(next) return next();
                return onOk?.(stringifyData);
              }
              if (data) {
                if(next) next();
                else onOk?.(stringifyData);
              }
            }
          }else {
            if(next) return next();
            return onOk?.();
          }
        }
      },
      async getGFORM_Data(flag?: boolean) {
        const data = await gformRef.current?.validateFields(flag ? true : false);
        return JSON.stringify(data || {});
      }
    }));

    const receiveMessage = useCallback(
      (event: any) => {
        const data = event.data;
        const action = data.action;

        if (action && data?.data) onOk?.(JSON.stringify(data.data));
      },
      [onOk]
    );

    useEffect(() => {
      window.addEventListener('message', receiveMessage, false);
      return () => {
        window.removeEventListener('message', receiveMessage);
      };
    }, [receiveMessage]);


    useEffect(() => {
      if (!formId) return;

      getForm(formId, formDataId).then(async (result) => {
        if (result.length) {
          const stateObj = state ? JSON.parse(state) : {};
          const [form, formData] = result;

          let _content: any = null;

          if (form.formEngine === 'LFORM') {

            // 直接渲染LFORM html模式
            if (isLformHtml) {
              _content = await getLformView(
                form.content,
                typeof formData.data === 'string' && formData.data ? JSON.parse(formData.data) : formData.data
              );
            } else {
              _content = form.content;
            }
          } else {
            // gform
            _content = form.content;
          }

          formEngine.current = form.formEngine;

          if (formData?.data) {
            setFormData(formData.data);
          } else if (stateObj.variables?.init) {
            setFormData(JSON.stringify(stateObj.variables.init));
          }

          setContent(_content);
          setEnviromentConfig(form.enviromentConfig);
          setFormInfo({ formDesc: form.formDesc, formName: form.formName });
        }
      });
    }, [url, formId, formDataId, isLformHtml, state]);

    const onLformLoad = useCallback(
      (e) => {
        e.target.style.height = e.target.contentWindow.document.documentElement.scrollHeight + 15 + 'px';
        lformRef.current?.contentWindow?.postMessage(
          {
            action: action || 'nodeEdit',
            trackProcessNodeTemplateDef: content,
            trackProcessNodeTemplateData: formData && typeof formData === 'string' ? JSON.parse(formData) : formData,
            formName,
            taskId,
            state,
          },
          '*'
        );
      },
      [content, action, formName, state, formData, taskId]
    );

    const onLoad = useCallback((e) => {
      const target = e.target;
      target.style.height = target.contentWindow.document.documentElement.scrollHeight + 15 + 'px';

      setTimeout(() => {
        const childWlMain = target.contentWindow.document.querySelector('#wl-main');

        if (childWlMain) {
          const firstDev = childWlMain.querySelector('div');
          if (firstDev) target.style.height = firstDev.offsetHeight + 50 + 'px';
        }
      }, 1000);
    }, []);

    // 找出在当前节点可编辑的字段
    const [editFields, hideFields] = useMemo(() => {
      if (!state) return [];

      const parseState = JSON.parse(state);
      const huilian = parseState.huilian || {};
      const curTask = huilian[taskId!];

      if (!curTask) return [];

      const lpNodes = curTask.lpNodes || [];
      const invisibleList = curTask.invisibleList || [];

      return [lpNodes.map((item: any) => item.lpKey), invisibleList.map((item: any) => item.controlId)];
    }, [state, taskId]);

    const _url = useMemo(() => {
      if(url?.includes('printing')) return url + (url.includes('?') ? '&hidePrintBtn=true' : '?hidePrintBtn=true');
      return ''
    }, [url]);

    useEffect(() => {
      if (_url || formEngine.current === 'LFORM' || (isLformHtml && formEngine.current === 'LFORM')) {
        onTrigger?.('LFORM');
      }
    }, [_url, isLformHtml, onTrigger]);

    const _formData = useMemo(() => {
      return formData ? JSON.parse(formData) : {};
    }, [formData]);

    const _structure = useMemo(() => {
      if (content) {
        let _temp = JSON.parse(content);
        _temp.enviromentConfig = enviromentConfig ? JSON.parse(enviromentConfig!) : undefined;
        return _temp;
      }
      return {};
    }, [content, enviromentConfig]);

    if (_url) {
      return <iframe className="iframe" src={_url} width="100%" height="100%" title="formview" frameBorder="0" onLoad={(e) => onLoad(e)} />;
    }

    if (isLformHtml && formEngine.current === 'LFORM') {
      return <div dangerouslySetInnerHTML={{ __html: content }}></div>;
    }

    if (formEngine.current === 'LFORM') {
      return (
        <iframe
          className="iframe"
          ref={lformRef}
          onLoad={(e) => onLformLoad(e)}
          src={LFOFM_URL}
          width="100%"
          height="100%"
          title="LFORM"
          frameBorder="0"
        />
      );
    }

    return formEngine.current === 'GFORM' ? (
      <div style={pd}>
        <View
          formInfo={formInfo}
          editFields={editFields}
          hideFields={hideFields}
          data={_formData}
          ref={gformRef}
          disabled={disabled}
          structure={_structure}
          business={business}
        />
      </div>
    ) : null;
  }
);
